package com.gd.iot.energy.service.superadmin.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gd.iot.energy.code.ResponseCode;
import com.gd.iot.energy.consts.SystemConsts;
import com.gd.iot.energy.dao.superadmin.AdminPOMapper;
import com.gd.iot.energy.dao.superadmin.AdminRolePOMapper;
import com.gd.iot.energy.exception.MyException;
import com.gd.iot.energy.po.superadmin.AdminPO;
import com.gd.iot.energy.po.superadmin.AdminRolePO;
import com.gd.iot.energy.po.superadmin.AppAdminDetailPO;
import com.gd.iot.energy.pojo.superadmin.dto.AdminDTO;
import com.gd.iot.energy.pojo.superadmin.dto.AdminSaveDTO;
import com.gd.iot.energy.pojo.superadmin.vo.AdminPageVO;
import com.gd.iot.energy.pojo.common.vo.ColumnVO;
import com.gd.iot.energy.pojo.common.vo.PageVO;
import com.gd.iot.energy.pojo.superadmin.vo.AdminVO;
import com.gd.iot.energy.service.superadmin.AdminService;
import com.gd.iot.energy.service.superadmin.AppAdminDetailService;
import com.gd.iot.energy.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 用户管理
 */
@Service
public class AdminServiceImpl extends ServiceImpl<AdminPOMapper, AdminPO> implements AdminService {

    /**
     * 表头配置文件
     */
    private static final String ADMIN_LIST_COLUMN_FILE_NAME = "superadmin/admin_list.column";

    @Resource
    private AdminRolePOMapper adminRolePOMapper;

    @Resource
    private AdminPOMapper adminPOMapper;

    @Autowired
    private AppAdminDetailService appAdminDetailService;

    @Override
    public List<AdminRolePO> getAdminByRoleIds(List<Integer> ids) {
        return adminRolePOMapper.getAdminRolePOsByRoleId(ids, SystemConsts.EnergyTypeEnum.WATER.value);
    }

    @Override
    public PageVO<AdminPageVO> getPageAdminVOs(String username, String name, String email, Integer pageSize, Integer pageNum, String orderColumn, String orderType) {
        IPage<AdminPO> page = new Page<>(pageNum, pageSize);
        QueryWrapper<AdminPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_del", SystemConsts.BooleanEnum.FALSE.value);
        if (StrUtil.isNotBlank(username)) {
            queryWrapper.like("username", username.trim());
        }
        if (StrUtil.isNotBlank(name)) {
            queryWrapper.like("name", name.trim());
        }
        if (StrUtil.isNotBlank(email)) {
            queryWrapper.like("email", email.trim());
        }

        if (StrUtil.isNotBlank(orderColumn) && StrUtil.isNotBlank(orderType)) {
            orderColumn = CustomStrUtil.humpToLine(orderColumn);
            queryWrapper.orderBy(true, orderType.equals(SystemConsts.OrderType.ASC.value), orderColumn);
        }
        EnergyTypeUtil.injectEnergyTypeWrapper(queryWrapper);
        IPage<AdminPO> adminPOPage = adminPOMapper.selectPage(page, queryWrapper);
        PageVO<AdminPageVO> pageVO = new PageVO<>();
        pageVO.setPageSize(pageSize);
        pageVO.setPageNum(pageNum);
        List<AdminPageVO> roleVOList = convertToAdminPageVOList(adminPOPage.getRecords());
        pageVO.setData(roleVOList);
        pageVO.setTotal(adminPOPage.getTotal());
        pageVO.setPages(adminPOPage.getPages());

        //表头
        List<ColumnVO> columns = CustomColumnUtil.getColumn(ADMIN_LIST_COLUMN_FILE_NAME);
        pageVO.setColumns(columns);
        return pageVO;
    }

    @Override
    public AdminSaveDTO getAdmin(Integer id) {
        AdminPO adminPO = adminPOMapper.selectById(id);
        if(adminPO==null||SystemConsts.BooleanEnum.TRUE.value.equals(adminPO.getIsDel())){
            throw new MyException(ResponseCode.RECORD_NOT_EXIST);
        }
//        AppAdminDetailPO appAdminDetailPO = appAdminDetailService.getOneByAdminId(id);

        AdminSaveDTO adminSaveDTO = new AdminSaveDTO();
        adminSaveDTO.setName(adminPO.getName());
        adminSaveDTO.setDepartment(adminPO.getDepartment());
        adminSaveDTO.setId(adminPO.getId());
        adminSaveDTO.setUsername(adminPO.getUsername());
        adminSaveDTO.setEmail(adminPO.getEmail());
        adminSaveDTO.setTelPhone(adminPO.getTelPhone());
        adminSaveDTO.setIsEnabled(adminPO.getIsEnabled());
//        if(appAdminDetailPO!=null) {
//            adminSaveDTO.setBalance(appAdminDetailPO.getBalance().toPlainString());
//            adminSaveDTO.setOvermoney(appAdminDetailPO.getOverMoney().toString());
//        }
        adminSaveDTO.setRoleIds(getRoleIdsByAdminId(adminPO.getId()));
        return adminSaveDTO;
    }

    /**
     * 获取管理员的角色id列表
     * @param adminId
     * @return
     */
    private List<Integer> getRoleIdsByAdminId(Long adminId) {
        QueryWrapper<AdminRolePO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", adminId);
        EnergyTypeUtil.injectEnergyTypeWrapper(queryWrapper);
        List<AdminRolePO> adminRolePOS = adminRolePOMapper.selectList(queryWrapper);
        return adminRolePOS.stream()
                .map(AdminRolePO::getRoleId)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long add(AdminSaveDTO adminSaveDTO) {
        if (StrUtil.isBlank(adminSaveDTO.getUsername())
                || StrUtil.isBlank(adminSaveDTO.getName())
                || StrUtil.isBlank(adminSaveDTO.getPassword())
                || StrUtil.isBlank(adminSaveDTO.getRePassword())) {
            throw new MyException(ResponseCode.PARAMETER_REQUIRED);
        }
        if (!adminSaveDTO.getPassword().equals(adminSaveDTO.getRePassword())) {
            throw new MyException(ResponseCode.PASSWORD_NOT_SAME);
        }
        if (isAdminExist(adminSaveDTO.getUsername())) {
            throw new MyException(ResponseCode.USER_NAME_IS_EXIST);
        }

        //邮箱合法性校验，可以为空，不为空格式需符合要求
        if (StrUtil.isNotBlank(adminSaveDTO.getEmail()) &&
                !CustomStrUtil.isEmail(adminSaveDTO.getEmail())) {
            throw new MyException(ResponseCode.EMAIL_FORMAT_ERROR);
        }

        AdminPO adminPO = new AdminPO();
        adminPO.setIsDel(SystemConsts.BooleanEnum.FALSE.value);
        adminPO.setName(adminSaveDTO.getName());
        adminPO.setUsername(adminSaveDTO.getUsername());
        adminPO.setCreateDate(new Date());
        adminPO.setEnergyType(SystemConsts.EnergyTypeEnum.WATER.value);
        adminPO.setIsLocked(SystemConsts.BooleanEnum.FALSE.value);
        adminPO.setEmail(adminSaveDTO.getEmail());
        adminPO.setTelPhone(adminSaveDTO.getTelPhone());
        adminPO.setPassword(PasswordUtil.generateHmacSHA1Password(adminSaveDTO.getPassword()));
        adminPO.setDepartment(adminSaveDTO.getDepartment());
        adminPO.setIsEnabled(adminSaveDTO.getIsEnabled());
        adminPO.setModifyDate(new Date());

        AdminDTO adminDTO = CurrentUserUtil.getUserInfo();
        adminPO.setOperatorId(adminDTO.getId());

        int num = adminPOMapper.insert(adminPO);
        if (num > 0) {
            saveAdminRoleRelation(adminSaveDTO.getRoleIds(), adminPO.getId());
            appAdminDetailService.saveDetail(adminSaveDTO.getBalance(), adminSaveDTO.getOvermoney(), adminPO.getId());
        }
        return adminPO.getId();
    }

    /**
     * 管理员是否存在
     *
     * @param username
     * @return
     */
    private boolean isAdminExist(String username) {
        QueryWrapper<AdminPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username.trim());
        Integer num = adminPOMapper.selectCount(queryWrapper);
        return num > 0;
    }

    /**
     * 角色 用户关联
     *
     * @param roleIds
     * @param adminId
     */
    private void saveAdminRoleRelation(List<Integer> roleIds, Long adminId) {
        if (adminId == null) {
            throw new MyException(ResponseCode.SYSTEM_ERROR);
        }
        if (CollUtil.isEmpty(roleIds)) {
            return;
        }

        //先删除
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("user_id", adminId);
        EnergyTypeUtil.injectEnergyTypeWrapper(queryWrapper);
        adminRolePOMapper.delete(queryWrapper);

        //再添加
        AdminRolePO adminRolePO;
        for (Integer roleId : roleIds) {
            if (roleId == null) {
                continue;
            }
            adminRolePO = new AdminRolePO();
            adminRolePO.setRoleId(roleId);
            adminRolePO.setUserId(adminId.intValue());
            adminRolePO.setEnergyType(SystemConsts.EnergyTypeEnum.WATER.value);
            adminRolePOMapper.insert(adminRolePO);
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateAdmin(AdminSaveDTO adminSaveDTO) {
        if (StrUtil.isBlank(adminSaveDTO.getUsername())
                || StrUtil.isBlank(adminSaveDTO.getName())
                || adminSaveDTO.getId() == null) {
            throw new MyException(ResponseCode.PARAMETER_REQUIRED);
        }

        //密码不为空判断密码是否相同
        boolean isNeedUpdatePassword = StrUtil.isNotBlank(adminSaveDTO.getPassword())
                                && StrUtil.isNotBlank(adminSaveDTO.getRePassword());
        if (isNeedUpdatePassword && !adminSaveDTO.getPassword().equals(adminSaveDTO.getRePassword())) {
            throw new MyException(ResponseCode.PASSWORD_NOT_SAME);
        }

        //邮箱合法性校验，可以为空，不为空格式需符合要求
        if (StrUtil.isNotBlank(adminSaveDTO.getEmail()) &&
                !CustomStrUtil.isEmail(adminSaveDTO.getEmail())) {
            throw new MyException(ResponseCode.EMAIL_FORMAT_ERROR);
        }

        AdminPO adminPO = new AdminPO();
        adminPO.setId(adminSaveDTO.getId());
        adminPO.setIsDel(SystemConsts.BooleanEnum.FALSE.value);
        adminPO.setName(adminSaveDTO.getName());
        adminPO.setTelPhone(adminSaveDTO.getTelPhone());
        adminPO.setEnergyType(SystemConsts.EnergyTypeEnum.WATER.value);
        adminPO.setIsLocked(SystemConsts.BooleanEnum.FALSE.value);
        adminPO.setEmail(adminSaveDTO.getEmail());
        if(isNeedUpdatePassword) {
            adminPO.setPassword(PasswordUtil.generateHmacSHA1Password(adminSaveDTO.getPassword()));
        }
        adminPO.setDepartment(adminSaveDTO.getDepartment());
        adminPO.setIsEnabled(adminSaveDTO.getIsEnabled());
        adminPO.setModifyDate(new Date());

        AdminDTO adminDTO = CurrentUserUtil.getUserInfo();
        adminPO.setOperatorId(adminDTO.getId());

        //更新基础数据
        adminPOMapper.updateById(adminPO);

        //保存管理员角色关系
        saveAdminRoleRelation(adminSaveDTO.getRoleIds(), adminPO.getId());

        //更新详情
//        appAdminDetailService.updateDetail(adminSaveDTO.getBalance(), adminSaveDTO.getOvermoney(), adminPO.getId());

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(List<Integer> ids) {
        if(CollUtil.isEmpty(ids)){
            throw new MyException(ResponseCode.PARAMETER_REQUIRED);
        }

        //管理员表逻辑删除
        QueryWrapper<AdminPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id", ids);
        EnergyTypeUtil.injectEnergyTypeWrapper(queryWrapper);
        AdminPO adminPO = new AdminPO();
        adminPO.setIsDel(SystemConsts.BooleanEnum.TRUE.value);
        int num = adminPOMapper.update(adminPO,queryWrapper);

        //管理员详情表逻辑删除
//        appAdminDetailService.deleteByAdminIds(ids);
        return num > 0;
    }

    @Override
    public List<AdminVO> getAllAdmin() {
        QueryWrapper<AdminPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("is_del", SystemConsts.BooleanEnum.FALSE.value);
        EnergyTypeUtil.injectEnergyTypeWrapper(queryWrapper);
        List<AdminPO> list = list(queryWrapper);
        List<AdminVO> res = new ArrayList<>(list.size());
        CustomBeanUtils.convertPojo(list,res,AdminVO.class);
        return res;
    }

    /**
     * 转成 RolePageVO
     *
     * @param records
     * @return
     */
    private List<AdminPageVO> convertToAdminPageVOList(List<AdminPO> records) {
        List<AdminPageVO> res = new ArrayList<>(records.size());

        List<Long> adminIds = records.stream()
                .map(AdminPO::getId)
                .collect(Collectors.toList());

        List<AppAdminDetailPO> appAdminDetailPOList = appAdminDetailService.getAppAdminDetailPOByRoleIds(adminIds);
        Map<Long, BigDecimal> adminIdBalanceMap = appAdminDetailPOList.stream()
                .collect(Collectors.toMap(AppAdminDetailPO::getAdminId, AppAdminDetailPO::getBalance));
        AdminPageVO adminPageVO;
        for (AdminPO record : records) {
            adminPageVO = new AdminPageVO();
            adminPageVO.setId(record.getId());
            adminPageVO.setName(record.getName());
            adminPageVO.setUsername(record.getUsername());
            adminPageVO.setEmail(record.getEmail());
            String balance = adminIdBalanceMap.get(record.getId()) != null ? adminIdBalanceMap.get(record.getId()).toPlainString() : null;
            adminPageVO.setBalance(balance);
            adminPageVO.setLoginIp(record.getLoginIp());
            adminPageVO.setLoginDate(DateUtil.formatDate(record.getLoginDate()));
            adminPageVO.setCreateDate(DateUtil.formatDate(record.getCreateDate()));
            adminPageVO.setIsEnabled(SystemConsts.StatusEnum.getNameByValue(record.getIsEnabled()));
            res.add(adminPageVO);
        }
        return res;

    }
}
